package com.tarena.lbs.business.dao.mapper.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.business.dao.mapper.StoreMapper;
import com.tarena.lbs.business.dao.repository.StoreRepository;
import com.tarena.lbs.business.pojo.po.BusinessPO;
import com.tarena.lbs.business.pojo.po.StorePO;
import com.tarena.lbs.business.pojo.query.StoreQuery;
import com.tarena.lbs.business.pojo.vo.StoreVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.data.redis.core.GeoOperations;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.stream.Collectors;

@Repository
public class StoreRepositoryImpl implements StoreRepository {
    @Autowired
    private StoreMapper storeMapper;
    @Qualifier("redisTemplate")
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public PageInfo<StorePO> pageStoreList(StoreQuery query) {
        // 启动分页
        PageHelper.startPage(query.getPageNo(), query.getPageSize());
        // 执行查询
        List<StorePO> stores = storeMapper.getAllStores(query);
        // 封装分页信息
        return new PageInfo<>(stores);
    }

    @Override
    public List<StoreVO> getNearbyStores(String longitude, String latitude) {
        // 1. 获取RedisGeo操作对象
        GeoOperations<String, Integer> geoOps = redisTemplate.opsForGeo();

        // 2. 创建查询圆圈
        Circle circle = new Circle(
                new Point(Double.parseDouble(longitude),Double.parseDouble(latitude)),
                1000); // 1公里半径

        // 3. 设置查询参数
        RedisGeoCommands.GeoRadiusCommandArgs args =
                RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                        .includeCoordinates()
                        .includeDistance();

        // 4. 执行地理查询
        GeoResults<RedisGeoCommands.GeoLocation<Integer>>geoResults =
                geoOps.radius("store:geo:all", circle, args);

        // 5. 获取查询结果并转换为StoreVO列表
        return geoResults.getContent().stream()
                .map(result -> {
                    // 获取距离信息
                    Distance distance = result.getDistance();
                    BigDecimal distValue = new BigDecimal(distance.getValue() + "").setScale(2, RoundingMode.HALF_UP);

                    // 获取店铺ID和坐标
                    Integer storeId = result.getContent().getName();
                    double lng = result.getContent().getPoint().getX();
                    double lat = result.getContent().getPoint().getY();

                    // 获取店铺详细信息
                    StorePO storePO = getStoreById(storeId);
                    String storeName = storePO.getStoreName();
                    Integer storeStatus = storePO.getStoreStatus();

                    // 封装为StoreVO
                    StoreVO vo = new StoreVO();
                    vo.setId(storeId);
                    vo.setStoreName(storeName);
                    vo.setStoreStatus(storeStatus);
                    vo.setStoreLongitude(String.valueOf(lng));
                    vo.setStoreLatitude(String.valueOf(lat));
                    return vo;
                })
                .collect(Collectors.toList());
    }

    private StorePO getStoreById(Integer storeId) {
        return storeMapper.getStoreById(storeId);
    }


    @Override
    public List<StorePO> getStores() {
        return storeMapper.getStores();
    }

    @Override
    public void insertStore(StorePO storePO) {
        storeMapper.insertStore(storePO);
    }

    @Override
    public BusinessPO getBusinessById(Integer businessId) {
        return storeMapper.getBusinessById(businessId);
    }

    @Override
    public List<StorePO> queryStoresByAreaAndBusiness(List<Long> cityIdList, Integer businessId) {
        return storeMapper.queryStoresByAreaAndBusiness(cityIdList, businessId);
    }
}
